
package net;

import java.io.*;
import java.net.Socket;
import java.util.*;
import net.message.*;

/**
 * Represents conversation service thread.
 * @author Paweł
 */
public class ConversationService extends Observable implements Runnable {
    private Socket socket;
    private BufferedReader input;
    private PrintWriter output;
    private boolean finish = false;

    /**
     * Creates new conversation service with given destination point.
     * @param socket - destination
     * @throws IOException
     */
    public ConversationService(Socket socket) throws IOException {
        this.socket = socket;
        input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        output = new PrintWriter(socket.getOutputStream(), true);
    }

    /**
     * Sends hello message of implemented protocol
     * @param name - username sent in hello message
     */
    public void sendHello(String name) {
        output.println(Protocol.HELLO + Protocol.DELIMITER + name);
    }

    /**
     * Sends text to destination point.
     * @param text - text of the messsage
     */
    public void sendText(String text) {
        text = text.replaceAll(Protocol.DELIMITER, "<delimiter>").replaceAll("\n|\r", "<newline>");
        output.println(Protocol.MESSAGE + Protocol.DELIMITER + text);
    }

    /**
     * Sends bye message of implemented protocol and stops service.
     */
    public void sendBye() {
        output.write(Protocol.BYE + "\n");
        try {
            socket.close();
            finish = true;
        } catch (IOException ex) {
            throw new RuntimeException(ex);
        }
    }

    /**
     * Closes connection and stops the service
     * @throws IOException
     */
    synchronized public void closeConnection() throws IOException {
        //output.write(Protocol.BYE + "\n");
        finish = true;
        socket.close();
    }

    public void run() {
        while (!finish) {
            try {
                StringTokenizer stringTokenizer = new StringTokenizer(input.readLine(), Protocol.DELIMITER);
                String token = stringTokenizer.nextToken();
                if (token.equals(Protocol.MESSAGE)) {
                    setChanged();
                    notifyObservers(new MessageMessage(
                       stringTokenizer.nextToken().replaceAll("<newline>", "\n").replaceAll("<delimiter>", Protocol.DELIMITER)
                    ));
                } else if (token.equals(Protocol.HELLO)) {
                    setChanged();
                    notifyObservers(new HelloMessage(stringTokenizer.nextToken()));
                } else if (token.equals(Protocol.BYE)) {
                    socket.close();
                    setChanged();
                    notifyObservers(new ByeMessage(""));
                    break;
                }
            } catch (IOException ex) {
                setChanged();
                notifyObservers(new ErrorMessage("Error when reading message"));
            }
        }
    }

}
